const bcrypt = require('bcryptjs')

const {
    sequelize
} = require('../../core/db')


const {
    Sequelize,
    Model
} = require('sequelize')


const redisClient = require('../../core/redis');
const {success} = require("../lib/helper"); // 引入 Redis 客户端

// define
class User extends Model {
    static async verifyEmailPassword(email, plainPassword) {
        const user = await User.findOne({
            where: {
                email
            }
        })

        if (!user) {
            throw new global.errs.AuthFailed('账号不存在或密码错误');
        }

        if (user.logout === 0) {
            throw new global.errs.AuthFailed('账号已被注销，请联系管理员');
        }

        const attemptKey = `login:attempts:${email}`;
        const lockoutKey = `login:lockout:${email}`;

        // 检查用户是否被锁定
        const lockoutTime = await redisClient.get(lockoutKey);
        if (lockoutTime && new Date().getTime() < new Date(lockoutTime).getTime()) {
            throw new global.errs.AuthFailed('账号或者密码输入多次错误，请稍后重试')
            return;
        }

        // user.password === plainPassword
        const correct = bcrypt.compareSync(
            plainPassword, user.password)
        if (!user || !correct) {

            // 密码错误，增加尝试次数
            let attempts = parseInt(await redisClient.get(attemptKey)) || 0;
            attempts++;

            // 更新尝试次数
            await redisClient.set(attemptKey, attempts);

            // 检查是否达到最大尝试次数
            if (attempts >= 5) {
                // 设置锁定时间（15分钟后）
                const lockoutExpiry = new Date().getTime() + 15 * 60 * 1000;
                await redisClient.setex(lockoutKey, 15 * 60, lockoutExpiry.toString());
                throw new global.errs.AuthFailed('账号或者密码输入多次错误，请稍后重试')
                return;
            }

            throw new global.errs.AuthFailed('账号不存在或密码错误')
            return;
        }

        // 可选：登录成功后清除尝试次数
        await redisClient.del(attemptKey);
        await redisClient.del(lockoutKey);
        return user
    }


    static async findByPk(id) {
        const user = await User.findOne({
            where: {
                id
            }
        })
        return user
    }
}


User.init({
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
        autoIncrement: true
    },
    nickname: Sequelize.STRING,
    phone: Sequelize.STRING,
    idcard: Sequelize.STRING,
    location: Sequelize.STRING,
    email: {
        type: Sequelize.STRING(128),
        unique: true
    },
    admin: Sequelize.INTEGER,
    logout: Sequelize.INTEGER,
    password: {
        //扩展 设计模式 观察者模式
        //ES6 Reflect Vue3.0
        type: Sequelize.STRING,
        set(val) {
            const salt = bcrypt.genSaltSync(10)
            const psw = bcrypt.hashSync(val, salt)
            this.setDataValue('password', psw)
        }
    },
}, {
    sequelize,
    tableName: 'user'
})

module.exports = {
    User
}

// 数据迁移 SQL 更新 风险
